//
//  FoundationArchiver.swift
//  ZipTool
//
//  Created by jerry on 2025/9/14.
//

import Foundation
import Compression

class FoundationArchiver {
    
    static func createZipArchive(items: [CompressionItem], destinationURL: URL, progressHandler: @escaping (Double) -> Void) throws {
        // 使用 Foundation 的 NSFileCoordinator 来安全访问文件
        var coordinatedItems: [(URL, Data)] = []
        let coordinator = NSFileCoordinator()
        var coordinatorError: NSError?
        
        let totalItems = items.count
        
        // 读取所有文件数据
        for (index, item) in items.enumerated() {
            if !item.isDirectory {
                coordinator.coordinate(readingItemAt: item.url, options: [], error: &coordinatorError) { (url) in
                    do {
                        let data = try Data(contentsOf: url)
                        coordinatedItems.append((item.url, data))
                    } catch {
                        print("Error reading file: \(error)")
                    }
                }
                
                if let error = coordinatorError {
                    throw error
                }
            }
            
            DispatchQueue.main.async {
                progressHandler(Double(index + 1) / Double(totalItems) * 0.5)
            }
        }
        
        // 创建 ZIP 数据
        let zipData = try createZipData(from: items, fileData: coordinatedItems, progressHandler: { progress in
            DispatchQueue.main.async {
                progressHandler(0.5 + progress * 0.5)
            }
        })
        
        // 写入目标文件
        coordinator.coordinate(writingItemAt: destinationURL, options: [], error: &coordinatorError) { (url) in
            do {
                try zipData.write(to: url)
            } catch {
                print("Error writing zip file: \(error)")
            }
        }
        
        if let error = coordinatorError {
            throw error
        }
        
        DispatchQueue.main.async {
            progressHandler(1.0)
        }
    }
    
    private static func createZipData(from items: [CompressionItem], fileData: [(URL, Data)], progressHandler: @escaping (Double) -> Void) throws -> Data {
        // 简化的 ZIP 文件创建
        // 这里我们使用一个基本的实现，实际项目中可能需要更完整的 ZIP 格式支持
        
        var zipData = Data()
        let fileDataDict = Dictionary(uniqueKeysWithValues: fileData)
        
        // ZIP 文件头
        let zipHeader = Data([0x50, 0x4B, 0x03, 0x04]) // ZIP 本地文件头签名
        
        for (index, item) in items.enumerated() {
            if !item.isDirectory, let data = fileDataDict[item.url] {
                // 添加文件到 ZIP
                zipData.append(zipHeader)
                
                // 简化的文件头信息
                let nameData = item.relativePath.data(using: .utf8) ?? Data()
                let nameLength = UInt16(nameData.count)
                
                // 版本、标志、压缩方法等（简化）
                zipData.append(Data([0x14, 0x00])) // 版本
                zipData.append(Data([0x00, 0x00])) // 标志
                zipData.append(Data([0x00, 0x00])) // 压缩方法（存储）
                zipData.append(Data([0x00, 0x00, 0x00, 0x00])) // 时间和日期
                zipData.append(Data([0x00, 0x00, 0x00, 0x00])) // CRC-32
                
                // 文件大小
                let fileSize = UInt32(data.count)
                withUnsafeBytes(of: fileSize.littleEndian) { zipData.append(Data($0)) }
                withUnsafeBytes(of: fileSize.littleEndian) { zipData.append(Data($0)) }
                
                // 文件名长度
                withUnsafeBytes(of: nameLength.littleEndian) { zipData.append(Data($0)) }
                zipData.append(Data([0x00, 0x00])) // 额外字段长度
                
                // 文件名
                zipData.append(nameData)
                
                // 文件数据
                zipData.append(data)
            }
            
            progressHandler(Double(index + 1) / Double(items.count))
        }
        
        // ZIP 中央目录结束记录
        zipData.append(Data([0x50, 0x4B, 0x05, 0x06])) // 结束签名
        zipData.append(Data(repeating: 0x00, count: 18)) // 简化的结束记录
        
        return zipData
    }
}